package com.xy.netty.dome.life.cycle.bound.handler.in;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @author 1
 * 讲解Channel作用，核心模块知识点，生命周期等
 *
 *         什么是Channel: 客户端和服务端建立的一个连接通道
 *         什么是ChannelHandler： 负责Channel的逻辑处理
 *         什么是ChannelPipeline: 负责管理ChannelHandler的有序容器
 *
 *     他们是什么关系:
 *                 一个Channel包含一个ChannelPipeline，所有ChannelHandler都会顺序加入到ChannelPipeline中
 *                 创建Channel时会自动创建一个ChannelPipeline，每个Channel都有一个管理它的pipeline，这关联是永久性的
 *
 *
 *         Channel当状态出现变化，就会触发对应的事件
 *
 *         状态：
 *             （1）channelRegistered: channel注册到一个EventLoop
 *
 *             （2）channelActive: 变为活跃状态（连接到了远程主机），可以接受和发送数据
 *
 *             （3）channelInactive: channel处于非活跃状态，没有连接到远程主机
 *
 *             （4）channelUnregistered: channel已经创建，但是未注册到一个EventLoop里面，也就是没有和Selector绑定
 */

@Slf4j
public class InboundHandlerOne extends ChannelInboundHandlerAdapter {
    /**
     * 第一个开始调用、 第一次连接调用
     */
    public InboundHandlerOne() {
        super();
        log.info("InboundHandlerOne");
    }

    /**
     * 第二个调用、 客户端注册、第一次连接调用
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        log.info("InboundHandlerOne channelRegistered");
        super.channelRegistered(ctx);
    }

    /**
     * 第三个调用 、 活跃 、第一次连接调用
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("InboundHandlerOne channelActive");
        super.channelActive(ctx);
    }

    /**
     * 第四个调用 或 读取数据局
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf data = (ByteBuf) msg;
        log.info("InboundHandlerOne channelRead 服务端收到数据：{}",data.toString(CharsetUtil.UTF_8));
        // 执行下一个InboundHandler
        ctx.fireChannelRead(Unpooled.copiedBuffer(data.toString(CharsetUtil.UTF_8), CharsetUtil.UTF_8));
    }

    /**
     * 第五个 调用 读书数据完成
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        log.info("InboundHandlerOne channelReadComplete");
        ctx.flush();
    }

    /**
     * 第六个调用，当用户断开 或 系统出现异常被调用
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("InboundHandlerOne->exceptionCaught",cause);
        ctx.close();
    }

    /**
     * 第七个调用，当用户断开 或  用户事件触发
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        log.info("InboundHandlerOne userEventTriggered，evt：{}",evt);
        super.userEventTriggered(ctx, evt);
    }

    /**
     * 第八个调用 当用户断开 或  客户端 失去连接
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("InboundHandlerOne channelInactive");
        super.channelInactive(ctx);
    }

    /**
     * 第九个被调用 当用户断开 或 删除 客户端注册
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        log.info("InboundHandlerOne channelUnregistered");
        super.channelUnregistered(ctx);
    }

}
